package inet.app.tuvi.activity;

import inet.app.tuvi.R;
import inet.app.tuvi.base.BaseFragment;
import inet.app.tuvi.base.BaseFragmentActivity;
import inet.app.tuvi.config.AppConstants;
import inet.app.tuvi.fragment.AppKhacFragment;
import inet.app.tuvi.fragment.GioiThieuFragment;
import inet.app.tuvi.fragment.TuViFragment;
import inet.app.tuvi.fragment.TuoiXongDatFragment;
import inet.app.tuvi.fragment.VanHanFragment;

import java.util.HashMap;
import java.util.Stack;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;

public class MainActivity extends BaseFragmentActivity implements
		OnTabChangeListener {

	private TabHost mTabHost;

	/* A HashMap of stacks, where we use tab identifier as keys.. */
	private HashMap<String, Stack<Fragment>> mStacks = new HashMap<String, Stack<Fragment>>();
	private String mCurrentTab;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initModels();
		initViews();
	}

	private void initModels() {
		/*
		 * Navigation stacks for each tab gets created.. tab identifier is used
		 * as key to get respective stack for each tab
		 */
		mStacks.put(AppConstants.TAB_TUVI, new Stack<Fragment>());
		mStacks.put(AppConstants.TAB_VANHAN, new Stack<Fragment>());
		mStacks.put(AppConstants.TAB_TUOIXONGDAT, new Stack<Fragment>());
		mStacks.put(AppConstants.TAB_GIOITHIEU, new Stack<Fragment>());
		mStacks.put(AppConstants.TAB_APP_KHAC, new Stack<Fragment>());
	}

	private void initViews() {
		initTabHost();
	}

	private void initTabHost() {
		mTabHost = (TabHost) findViewById(android.R.id.tabhost);
		mTabHost.setOnTabChangedListener(this);
		mTabHost.setup();
		
		mTabHost.setCurrentTab(-3);
		initTabSpec(AppConstants.TAB_TUVI);
		initTabSpec(AppConstants.TAB_VANHAN);
		initTabSpec(AppConstants.TAB_TUOIXONGDAT);
		initTabSpec(AppConstants.TAB_GIOITHIEU);
		initTabSpec(AppConstants.TAB_APP_KHAC);
	}
	
	private void initTabSpec(String tabId) {
		TabHost.TabSpec spec = mTabHost.newTabSpec(tabId);

		// initialize tab content
		spec.setContent(new TabHost.TabContentFactory() {
			public View createTabContent(String tag) {
				return findViewById(R.id.realtabcontent);
			}
		});
		
		//initialize tab view
		int resId;
		String tabName;
		if(tabId.equals(AppConstants.TAB_TUVI)) {
			resId = R.drawable.tuvi_tab_selector;
			tabName = getString(R.string.tu_vi);
		} else if(tabId.equals(AppConstants.TAB_VANHAN)) {
			resId = R.drawable.vanhan_tab_selector;
			tabName = getString(R.string.van_han);
		} else if(tabId.equals(AppConstants.TAB_TUOIXONGDAT)) {
			resId = R.drawable.tuoixongdat_tab_selector;
			tabName = getString(R.string.tuoi_xong_dat);
		} else if(tabId.equals(AppConstants.TAB_GIOITHIEU)) {
			resId = R.drawable.gioithieu_tab_selector;
			tabName = getString(R.string.gioi_thieu);
		} else {
			resId = R.drawable.appkhac_tab_selector;
			tabName = getString(R.string.app_khac);
		}
		spec.setIndicator(createTabView(resId,
				tabName, this));
		mTabHost.addTab(spec);
	}

	private static View createTabView(final int id, final String title,
			Context context) {

		View view = LayoutInflater.from(context).inflate(R.layout.tabs_icon,
				null);
		ImageView imageView = (ImageView) view.findViewById(R.id.tab_icon);
		imageView.setImageDrawable(context.getResources().getDrawable(id));

		TextView textView = (TextView) view.findViewById(R.id.tab_title);
		if (TextUtils.isEmpty(title)) {
			textView.setVisibility(View.GONE);
		} else {
			textView.setText(title);
		}
		return view;
	}

	/**
	 * Might be useful if we want to switch tab programmatically, from inside
	 * any of the fragment.
	 */
	public void setCurrentTab(int val) {
		mTabHost.setCurrentTab(val);
	}
	
	/**
	 * To add fragment to a tab. tag -> Tab identifier fragment -> Fragment to
	 * show, in tab identified by tag shouldAnimate -> should animate
	 * transaction. false when we switch tabs, or adding first fragment to a tab
	 * true when when we are pushing more fragment into navigation stack.
	 * shouldAdd -> Should add to fragment navigation stack (mStacks.get(tag)).
	 * false when we are switching tabs (except for the first time) true in all
	 * other cases.
	 */
	public void pushFragments(String tag, Fragment fragment,
			boolean shouldAnimate, boolean shouldAdd) {
		if (shouldAdd)
			mStacks.get(tag).push(fragment);
		FragmentTransaction ft = mFragmentManager.beginTransaction();
		if (shouldAnimate)
			ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
		ft.replace(R.id.realtabcontent, fragment);
		ft.commit();
	}

	public void popFragments() {
		/*
		 * Select the second last fragment in current tab's stack.. which will
		 * be shown after the fragment transaction given below
		 */
		Fragment fragment = mStacks.get(mCurrentTab).elementAt(
				mStacks.get(mCurrentTab).size() - 2);

		/* pop current fragment from stack.. */
		mStacks.get(mCurrentTab).pop();

		/*
		 * We have the target fragment in hand.. Just show it.. Show a standard
		 * navigation animation
		 */
		FragmentManager manager = getSupportFragmentManager();
		FragmentTransaction ft = manager.beginTransaction();
		// ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
		ft.replace(R.id.realtabcontent, fragment);
		ft.commit();
	}
	
	@Override
	public void onBackPressed() {
		if (mStacks.get(mCurrentTab).lastElement() instanceof BaseFragment) {
			if (((BaseFragment) mStacks.get(mCurrentTab).lastElement())
					.onBackPressed() == false) {
				/*
				 * top fragment in current tab doesn't handles back press, we
				 * can do our thing, which is
				 * 
				 * if current tab has only one fragment in stack, ie first
				 * fragment is showing for this tab. finish the activity else
				 * pop to previous fragment in stack for the same tab
				 */
				if (mStacks.get(mCurrentTab).size() == 1) {
					super.onBackPressed(); // or call finish..
				} else {
					popFragments();
				}
			}
		} else {
			// do nothing.. fragment already handled back button press.
		}
	}
	
	@Override
	public void onTabChanged(String tabId) {
		// TODO Auto-generated method stub
		mCurrentTab = tabId;
		
		if (mStacks.get(tabId).size() == 0) {
			/*
			 * First time this tab is selected. So add first fragment of that
			 * tab. Dont need animation, so that argument is false. We are
			 * adding a new fragment which is not present in stack. So add to
			 * stack is true.
			 */
			if (tabId.equals(AppConstants.TAB_TUVI)) {
				pushFragments(tabId, TuViFragment.newInstance(), false,
						true);
			} else if (tabId.equals(AppConstants.TAB_VANHAN)) {
				pushFragments(tabId, VanHanFragment.newInstance(), false,
						true);
			} else if (tabId.equals(AppConstants.TAB_TUOIXONGDAT)) {
				pushFragments(tabId, TuoiXongDatFragment.newInstance(), false,
						true);
			} else if (tabId.equals(AppConstants.TAB_GIOITHIEU)) {
				pushFragments(tabId, GioiThieuFragment.newInstance(), false,
						true);
			} else {
				pushFragments(tabId, AppKhacFragment.newInstance(), false,
						true);
			}
		} else {
			/*
			 * We are switching tabs, and target tab is already has atleast one
			 * fragment. No need of animation, no need of stack pushing. Just
			 * show the target fragment
			 */
			pushFragments(tabId, mStacks.get(tabId).lastElement(), false, false);
		}
	}

}
